package edu.asu.sefcom.extract.profile.data;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;

import org.apache.log4j.Logger;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;
import org.neo4j.kernel.EmbeddedGraphDatabase;

import scala.actors.threadpool.Arrays;
import edu.asu.sefcom.extract.profile.data.Neo4jConnector.MyRelationshipTypes;

public class Queries {

	Logger logger = Logger.getLogger(Queries.class);

	public static void main(String[] args) {
		Queries queries = new Queries();
		Properties properties = new Properties();
		try {
			properties.load(new FileInputStream("config/app.properties"));
		} catch (IOException e) {
		}
		String dbDir = ""
				+ properties
						.getProperty("edu.asu.sefcom.extract.profile.database.dir");
		EmbeddedGraphDatabase graphDB = null;
		try {
			graphDB = new EmbeddedGraphDatabase(dbDir);
			// queries.personFollows(graphDB);
			queries.personwithmostarticlesforgroup(graphDB);
		} finally {
			queries.shutdown(graphDB);
		}
	}

	public void personFollows(EmbeddedGraphDatabase databaseService) {
		// string array here

		String[] argsbhcrew = new String[] { "90h", "agregatore", "alex",
				"andy", "ark", "bhcrew", "break", "bub", "buk", "bz", "cgi",
				"chaotist", "cold", "count", "cqi", "crash", "cut", "cyb",
				"cyber", "d", "d5d", "daid", "dark", "delight", "devil", "dg",
				"dmnt", "domestic", "drn", "enkrypt", "exit", "fill", "fluro",
				"generator", "glukkers", "guman", "hellman", "impud", "iret",
				"ispace", "its", "jack", "jd", "kalo", "klaster", "kolen",
				"krash", "kyp", "la", "aur", "lamer", "lj", "lucifer",
				"lutifer", "magic2k", "master", "mc", "med", "misha", "moi",
				"moon", "mor", "mrbuggers", "mr_hukker", "mummi", "n1k",
				"nait", "nitrex", "nomad", "noxp", "ns", "ocetp", "odept",
				"oskar", "panterka", "pedestrian", "perajok", "piska", "pitro",
				"pizza", "privac", "ram", "redhat", "redo", "renny", "sham",
				"stden", "sunx", "sww", "tim", "x90", "xs", "yen", "yuzvir",
				"z", "zdeus", "zenit", "zeppe1in", "zhen", "zloi" };
		String[] argscup = new String[] { "777bs", "c0der", "danila", "kiote",
				"lisnake", "moreno", "profit", "ww", "yi", "bzmrnkt", "cupsu",
				"kamarez", "lamarez", "mast3r", "panterka", "smix", "xcoder",
				"zaco" };
		String[] argsdamagelab = new String[] { "4kella", "357", "1983",
				"allotus", "brutt", "damagelab", "deface", "denchis", "dinar",
				"dvix", "ettee", "gam", "gr3", "ikso", "jerry", "kotuke",
				"n1d", "n1k", "psicho", "rev", "rubi", "the2kid", "winux",
				"xs", "zavu", "zd", "zx" };
		String[] argsmazafaka = new String[] { "beyond", "cr4sh", "d5d",
				"da99er", "daimik", "darlingkicks", "drnimnul", "ew4rk",
				"ignis_et_ferro", "marozz", "mazafaka_group", "nm", "r4dik",
				"rossoman", "spee_ua" };
		String[] argsruhack = new String[] { "bedr0s", "cr4sh", "eas7",
				"gruz0", "kirsanov_anton", "puzanov", "rstghc",
				"ru_hack_group", "stden", "vv6" };

		// for (String user : argsbhcrew) {
		// String[] args = new String[] { "bhcrew", user };
		// for (String user : argscup) {args = new String[] { "CUP", user };
		// for (String user : argsdamagelab) {args = new String[] {
		// "damagelab",user };
		// for (String user : argsmazafaka) {args = new String[] {
		// "mazafaka",user };
		int count = 0;
		for (Node user : databaseService.getAllNodes()) {
			try {
				try {
					System.out.println(user.getProperty("Type"));
					if (user.getProperty("Type").equals("User")) {
						count++;
						System.out.println(count);
					}
					List<Node> l1 = DBUtils.getAllNodeTypes(databaseService,
							"User");
					for (Node n : l1) {
						List<Node> l2 = DBUtils.getAllNodesInRel(n,
								MyRelationshipTypes.Follows, "User");
						if (l2.size() > 0) {
							System.out.println(n.getProperty("Name") + " - - "
									+ l2.size());
							// return;
						}
					}
					// System.out.println(l1.size());
				} catch (Exception e) {
				}
				// System.out.println(""+user.getPropertyKeys() +" "+count++);
				// printFollows1(databaseService,""+user.getProperty("Name"));
			} catch (Exception e) {
			}
		}

	}

	private void printFollows1(GraphDatabaseService graphDB, String user) {
		// TODO Auto-generated method stub
		Node node = DBUtils.getNodeByName(graphDB, user, "User");
		Map<String, Integer> map = new HashMap<String, Integer>();
		findFollows(node, map);
		logger.warn(map);
	}

	private void printFollows(String user) {
		// TODO Auto-generated method stub

	}

	private void personwithmostarticlesforgroup(EmbeddedGraphDatabase graphDB) {
		// TODO Auto-generated method stub
		List<Node> l2 = DBUtils.getAllNodeTypes(graphDB, "User");
		Map<String, Integer> follarticleCount = new HashMap<String, Integer>();
		for (Node node : l2) {
			findFollows(node, follarticleCount);
		}
		List<Entry<String, Integer>> sortedEntries = entriesSortedByValues(follarticleCount);

		Logger.getLogger(Queries.class).warn(sortedEntries);
		System.out.println(sortedEntries);
	}

	// 30186
	public void shutdown(EmbeddedGraphDatabase graphDB) {
		graphDB.shutdown();
	}

	private void findFollows(Node fUser, Map<String, Integer> follarticleCount) {
		try {
			String uName = "" + fUser.getProperty("Name");

			int followsCount = 0;
			for (Relationship relationship : fUser.getRelationships()) {
				if (("" + relationship.getType()).equals(""
						+ MyRelationshipTypes.Follows)) {
					Relationship folsrel = relationship;
					Iterable<Node> itr = Arrays.asList(folsrel.getNodes());
					for (Node nuser : itr) {
						for (String userProperty : nuser.getPropertyKeys()) {
							if ((userProperty).equals("Type")) {
								if (nuser.getProperty(userProperty).equals(
										"User")) {
									followsCount++;
								}
							}
						}
					}
				}
			}
			follarticleCount.put(uName, followsCount);
		} catch (Exception e) {
			System.out.println(e.getLocalizedMessage());
		}
	}

	<K, V extends Comparable<? super V>> List<Entry<K, V>> entriesSortedByValues(
			Map<K, V> map) {

		List<Entry<K, V>> sortedEntries = new ArrayList<Entry<K, V>>(
				map.entrySet());

		Collections.sort(sortedEntries, new Comparator<Entry<K, V>>() {
			@Override
			public int compare(Entry<K, V> e1, Entry<K, V> e2) {
				return e2.getValue().compareTo(e1.getValue());
			}
		});

		return sortedEntries;
	}

}
